package com.qire.common.collect;

import com.qire.common.function.Function;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * {@link Collection} 列表工具，提供更优雅的列表相关操作。
 */
public class ListUtil {

    /**
     * 是否为空
     * @param coll 判定对象
     * @return 容器为null或者没有数据为true,否则false
     */
    public static boolean isEmpty(Collection<?> coll) {
        return coll == null || coll.isEmpty();
    }

    /**
     * 是否不为空
     * @param coll 判定对象
     * @return 容器为null或者没有数据为false,否则true
     */
    public static boolean notEmpty(Collection<?> coll) {
        return !isEmpty(coll);
    }

    /**
     * 索引是否在目标容器范围内
     * @param coll 判断对象
     * @param index 指定索引
     * @return 如果容器为 null 或 index 不在容器可取范围内为 false，否则为 true
     */
    public static boolean range(Collection<?> coll, int index) {
        if(coll == null) {
            return false;
        }
        return index >= 0 && index < coll.size();
    }


    public static <E> boolean contains(Collection<E> coll, Function<E, Boolean> containsFunction) {
        for(E element : coll) {
            if(containsFunction.apply(element)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 逆转容器
     * @param list 目标容器
     * @return 逆转结果
     */
    public static <T extends List> void reverse(T list) {
        int first = 0, tail = list.size() - 1;
        int middle = tail >> 1;
        for( ; first <= middle; first++, tail--) {
            Object swap = list.get(first);
            list.set(first, list.get(tail));
            list.set(tail, swap);
        }
    }

    /**
     * 返回给定值在int范围内的值
     * @param value 给定值
     * @return 如果大于 {@link Integer#MAX_VALUE} 则返回 {@link Integer#MAX_VALUE}，
     *          如果小于 {@link Integer#MIN_VALUE} 则返回 {@link Integer#MIN_VALUE}，
     *          否则返回原值。
     */
    static int saturatedCast(long value) {
        if (value > Integer.MAX_VALUE) {
            return Integer.MAX_VALUE;
        }
        if (value < Integer.MIN_VALUE) {
            return Integer.MIN_VALUE;
        }
        return (int) value;
    }

    /**
     * 计算数组容量
     * @param arraySize 数组大小
     * @return 修正后大小
     */
    static int computeArrayListCapacity(int arraySize) {
        Preconditions.checkNonNegative(arraySize, "arraySize");
        return saturatedCast(5L + (long)arraySize + (long)(arraySize / 10));
    }

    /**
     * 创建建一个空的的可变ArrayList实例
     * @param <E> 列表元素类型
     * @return ArrayList
     */
    public static <E> ArrayList<E> newArrayList() {
        return new ArrayList();
    }

    /**
     * 创建包含给定元素的可变ArrayList实例
     * @param elements 给定元素
     * @param <E> 元素类型
     * @return 新的可变 ArrayList 实例
     */
    public static <E> ArrayList<E> newArrayList(E... elements) {
        Preconditions.checkNotNull(elements);
        int capacity = computeArrayListCapacity(elements.length);
        ArrayList<E> list = new ArrayList(capacity);
        Collections.addAll(list, elements);
        return list;
    }

    public static <E> ArrayList<E> newArrayList(Iterable<? extends E> elements) {
        Preconditions.checkNotNull(elements);
        return elements instanceof Collection ? new ArrayList((Collection) elements) : newArrayList(elements.iterator());
    }

    public static <E> ArrayList<E> newArrayList(Iterator<? extends E> elements) {
        ArrayList<E> list = newArrayList();
        IteratorUtil.addAll(list, elements);
        return list;
    }

    /**
     * 创建一个指定大小的 ArrayList 实例。
     * @param initialArraySize 指定大小
     * @param <E>
     * @return
     */
    public static <E> ArrayList<E> newArrayListWithCapacity(int initialArraySize) {
        Preconditions.checkNonNegative(initialArraySize, "initialArraySize");
        return new ArrayList(initialArraySize);
    }

    /**
     * 创建一个期望大小的 ArrayList 实例;
     * @param estimatedSize
     * @param <E>
     * @return
     */
    public static <E> ArrayList<E> newArrayListWithExpectedSize(int estimatedSize) {
        return new ArrayList(computeArrayListCapacity(estimatedSize));
    }

}
